3.7.2 对gb的介绍
gb是一个由Go社区成员开发的全新的构建工具。gb意识到,不一定要包装Go本身的工具,也可以使用其他方法来解决可重复构建的问题。
gb背后的原理源自理解到Go语言的 import
语句并没有提供可重复构建的能力。 import
语句可以驱动 go get
,但是 import
本身并没有包含足够的信息来决定到底要获取包的哪个修改的版本。 go get
无法定位待获取代码的问题,导致Go工具在解决重复构建时,不得不使用复杂且难看的方法。我们已经看到过使用 godep
时超长的导入路径是多么难看。
gb的创建源于上述理解。gb既不包装Go工具链,也不使用 GOPATH
。gb基于工程将Go工具链工作空间的元信息做替换。这种依赖管理的方法不需要重写工程内代码的导入路径。而且导入路径依旧通过 go get
和 GOPATH
工作空间来管理。
让我们看看上一节的工程如何转换为gb工程,如代码清单3-12所示。
代码清单3-12 gb
工程的例子
/home/bill/devel/myproject ($PROJECT)
|-- src
| |-- cmd
| | |-- myproject
| | | |-- main.go
| |-- examples
| |-- model
| |-- README.md
|-- vendor
|-- src
|-- bitbucket.org
| |-- ww
| |-- goautoneg
| |-- Makefile
| |-- README.txt
| |-- autoneg.go
| |-- autoneg_test.go
|-- github.com
|-- beorn7
|-- perks
|-- README.md
|-- quantile
|-- bench_test.go
|-- example_test.go
|-- exampledata.txt
|-- stream.go
一个gb工程就是磁盘上一个包含 src/
子目录的目录。符号 $PROJECT
导入了工程的根目录中,其下有一个 src/
的子目录中。这个符号只是一个简写,用来描述工程在磁盘上的位置。 $PROJECT
不是必须设置的环境变量。事实上,gb根本不需要设置任何环境变量。
gb工程会区分开发人员写的代码和开发人员需要依赖的代码。开发人员的代码所依赖的代码被称作 第三方代码 (vendored code)。gb工程会明确区分开发人员的代码和第三方代码,如代码清单3-13和代码清单3-14所示。
代码清单3-13 工程中存放开发人员写的代码的位置
$PROJECT/src/
代码清单3-14 存放第三方代码的位置
$PROJECT/vendor/src/
gb 一个最好的特点是,不需要重写 导入
路径。可以看看这个工程里的main.go文件的 import
语句——没有任何需要为导入第三方库而做的修改,如代码清单3-15所示。
代码清单3-15 gb工程的导入路径
01 package main
02
03 import (
04 "bitbucket.org/ww/goautoneg"
05 "github.com/beorn7/perks"
06 )
gb工具首先会在 $PROJECT/src/
目录中查找代码,如果找不到,会在 $PROJECT/vendor/src/
目录里查找。与工程相关的整个源代码都会在同一个代码库里。自己写的代码在工程目录的 src/
目录中,第三方依赖代码在工程目录的 vendor/src
子目录中。这样,不需要配合重写导入路径也可以完成整个构建过程,同时可以把整个工程放到磁盘的任意位置。这些特点,让gb成为社区里解决可重复构建的流行工具。
还需要提一点:gb工程与Go官方工具链(包括 go get
)并不兼容。因为gb不需要设置 GOPATH
,而Go工具链无法理解gb工程的目录结构,所以无法用Go工具链构建、测试或者获取代码。构建(如代码清单3-16所示)和测试gb工程需要先进入 $PROJECT
目录,并使用gb工具。
代码清单3-16 构建gb工程
gb build all
很多Go工具支持的特性,gb都提供对应的特性。gb还提供了插件系统,可以让社区扩展支持的功能。其中一个插件叫作 vendor
。这个插件可以方便地管理 $PROJECT/vendor/src/
目录里的依赖关系,而这个功能Go工具链至今没有提供。想了解更多gb的特性,可以访问这个网站:getgb.io。